package com.ewancle.utils;

public class SnowflakeIdGenerator {

    // 起始时间戳 (自定义的起始时间，通常为业务上线时间)
    private final long epoch = 1625133600000L;  // 2021-07-01 00:00:00 UTC

    // 各字段的位数
    private final long machineIdBits = 5L;    // 机器ID占的位数
    private final long dataCenterIdBits = 5L; // 数据中心ID占的位数
    private final long sequenceBits = 12L;    // 序列号占的位数

    // 各字段的最大值
    private final long maxMachineId = -1L ^ (-1L << machineIdBits); // 31
    private final long maxDataCenterId = -1L ^ (-1L << dataCenterIdBits); // 31
    private final long sequenceMask = -1L ^ (-1L << sequenceBits); // 4095

    // 位移量
    private final long machineIdShift = sequenceBits;
    private final long dataCenterIdShift = sequenceBits + machineIdBits;
    private final long timestampLeftShift = sequenceBits + machineIdBits + dataCenterIdBits;

    private long lastTimestamp = -1L;  // 上一次生成ID的时间戳
    private long sequence = 0L;  // 当前毫秒内的序列号
    private final long machineId;  // 机器ID
    private final long dataCenterId;  // 数据中心ID

    // 构造函数，初始化机器ID和数据中心ID
    public SnowflakeIdGenerator(long machineId, long dataCenterId) {
        if (machineId > maxMachineId || machineId < 0) {
            throw new IllegalArgumentException("Machine ID can't be greater than " + maxMachineId + " or less than 0");
        }
        if (dataCenterId > maxDataCenterId || dataCenterId < 0) {
            throw new IllegalArgumentException("DataCenter ID can't be greater than " + maxDataCenterId + " or less than 0");
        }
        this.machineId = machineId;
        this.dataCenterId = dataCenterId;
    }

    // 生成唯一ID
    public synchronized long generateId() {
        long timestamp = System.currentTimeMillis();

        // 如果当前时间戳小于上次生成ID的时间戳，说明系统时钟回退，抛出异常
        if (timestamp < lastTimestamp) {
            throw new RuntimeException("Clock moved backwards. Refusing to generate ID for " + (lastTimestamp - timestamp) + " milliseconds");
        }

        // 如果是同一毫秒内，序列号自增
        if (timestamp == lastTimestamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                // 当前毫秒内序列号已经用完，等待下一毫秒
                timestamp = waitNextMillis(lastTimestamp);
            }
        } else {
            // 不同毫秒内，重置序列号为0
            sequence = 0;
        }

        lastTimestamp = timestamp;

        // 生成ID
        return (timestamp - epoch) << timestampLeftShift  // 时间戳部分
                | (dataCenterId << dataCenterIdShift)  // 数据中心ID部分
                | (machineId << machineIdShift)        // 机器ID部分
                | sequence;                            // 序列号部分
    }

    // 等待直到下一毫秒
    private long waitNextMillis(long lastTimestamp) {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }

    public static void main(String[] args) {
        // 创建一个 ID 生成器实例，假设机器ID为1，数据中心ID为1
        SnowflakeIdGenerator generator = new SnowflakeIdGenerator(1, 1);

        // 测试生成ID
        for (int i = 0; i < 10; i++) {
            System.out.println(generator.generateId());
        }
    }
}
